"""
识别二维码
"""
import os
import re
import cv2
import fitz
import numpy as np
from pyzbar import pyzbar
from PIL import Image, ImageEnhance
import argparse


def get_qrcode(img, delta=15):
    """查找二维码"""
    img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
    original = img.copy()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
    contours, _ = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 只检测外轮廓，且只保留对角元素坐标
    areas = [cv2.contourArea(c) for c in contours]
    index = areas.index(max(areas))
    contour = contours[index]
    peri = cv2.arcLength(contour, True)
    approx = cv2.approxPolyDP(contour, 0.04 * peri, True)
    x,y,w,h = cv2.boundingRect(approx)
    ROI = original[y-delta:y+h+delta, x-delta:x+w+delta]
    return Image.fromarray(cv2.cvtColor(ROI, cv2.COLOR_BGR2RGB))


def get_qrcode_content(path, debug=False):
    """ 读取二维码的内容： img_adds：二维码地址（可以是网址也可是本地地址 """
    if path.endswith(('.pdf', '.PDF')):
        doc = fitz.Document(path)
        page = doc.load_page(0)
        _, _, width, height = page.rect
        pix = page.get_pixmap(clip=fitz.IRect(0, 0, width//5, height//4))
        img = Image.frombytes('RGB', [pix.width, pix.height], pix.samples)
    elif path.endswith(('.png', '.jpeg', '.bmp')):
        img = Image.open(path)
        width, height = img.size
        img = img.crop([0, 0, width//5, height//4])
    width, height = img.size
    ROI = get_qrcode(img.resize((width*3, height*3), Image.ANTIALIAS))
    ROI = ImageEnhance.Brightness(ROI).enhance(factor=1.5)
    if debug:
        print(f'=======ROI.size:{ROI.size}')
        ROI.show()
    txt = pyzbar.decode(ROI)[0]
    bar_code_data = txt.data.decode("utf-8")
    if debug:
        print(f'=======barcode text: {bar_code_data}')
    vli = re.split(r'[,，]', bar_code_data)
    if len(vli) < 8:
        raise Exception(f'Less data to parse! {bar_code_data}')
    inv_code = vli[2][:12]
    inv_num = vli[3][:10]
    inv_money = vli[4]
    inv_date = vli[5][:8]
    inv_chk = vli[6]
    return inv_code, inv_num, inv_date, inv_chk, inv_money


def test():
    for root, _, files in os.walk('pdf_dir'):
        for file_name in files:
            path = os.path.join(root, file_name)
            if path.endswith(('.pdf', '.PDF', '.png', '.jpg', '.jpeg', '.bmp')):
                try:
                    data = get_qrcode_content(path)
                    print(data)
                except Exception as e:
                    print(f'解析错误：{path} {e}')


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--path', required=True, type=str, help='输入文件路径')
    parser.add_argument('-d', '--debug', action='store_true', help='是否展示二维码')
    args = parser.parse_args()
    data = get_qrcode_content(args.path, args.debug)
    print(data)
